<?php
/**
 * 
 * @since 1:53 PM 12/05/2009
 * @author Tran Minh Huy <tranminhhuydn@gmail.com>
 * 
 */
class JstreeHelper extends Helper
{
	var $tab = "  ";
	var $admin='/';

  	var $helpers = array('Html','Javascript', 'Form');//, 'Seo');
  	
	var $model = "";
	var $prefix = "";
	var $controller = "";
	var $action = "";
	var $name = "";
	var $idDOM = "";
  	/**
  	* Installation css and js for tree
  	* @param boolean $option True if want render jquery-1.3.2.min.js 
 	* @return html content tag css and Javascript
 	* @access public  	
  	*/
	function initialize($option=false) {
		$html=$this->Html->css('jstree/tree_component');
		if($option)
		$html.=$this->Javascript->link('jstree/jquery-1.3.2.min');
		$html.=$this->Javascript->link('jstree/jquery.form');
		$html.=$this->Javascript->link('jstree/_lib');
		$html.=$this->Javascript->link('jstree/tree_component.min');
		return $html;
	}
	
	/**
	* Load the Tree menu
  	* @param string $id is id of HTML DOM
  	* @param array $dataTree
  	* @param mixed array $options
  	* For ex: $options = array('theme_name'=>'default','context_add'=>true,'context_edit'=>true,'context_delete'=>true,'context_copy'=>true,'context_paste'=>true,'context_changeicon'=>false);
  	* @return code block javascript include tag <script ...>
 	* @access public
	**/
	function load($id,$dataTree,$options=array()){
		//catch error
		if(empty($this->model)){
			trigger_error("<span style = \"color:Red;text-align:left\"><b>Mixed Model:</b> {$this->error}</span>", E_USER_WARNING);
			return;
		}
		if(empty($this->controller)){
			trigger_error("<span style = \"color:Red;text-align:left\"><b>Mixed Controller:</b> {$this->error}</span>", E_USER_WARNING);
			return;
		}
		$this->idDOM=$id;
		//create template form edit or add tree
		$prefix = (empty($this->prefix)?"":$this->prefix."/");
		$form ="
		<form id='jsTree{$id}Form' action='{$this->currentControllerPath}/edit_ajax' method='post' style='display:none'>
			<input type='text' id='jsTree{$id}FormId'  name='data[{$this->model}][id]' />
			<input type='text' id='jsTree{$id}FormName' name='data[{$this->model}][name]' />
			<input type='text' id='jsTree{$id}FormParentId' name='data[{$this->model}][parent_id]' />
		</form>";
		
		//marging options 
		$optionsDefault = array('type'=>'json','theme_name'=>'default','context_add'=>true,'context_edit'=>true,'context_delete'=>true,'context_copy'=>true,'context_paste'=>true,'context_changeicon'=>false);
		$optionsResult =  array_merge($optionsDefault, $options);
		$options = $optionsResult;
		
		//get data
		$data = $this->_ListJson($dataTree);
		
		$html="
			var jsTree{$id}Event={'edit':false,'add':false,'delete':false,'markLastNodeUpdate':null,'countPrev':null,'nextRequest':null};
			var jsTree{$id}Panel = {};
			var _test = Array();
			var jsTree{$id}Form = '';
			var jsTree{$id}FormId = '';
			var jsTree{$id}FormName = '';
			var jsTree{$id}FormParentId = '';
			
			//return count prev node
			function jsTreeGetPosition(NODE){
				 var count = 0;
				 var prev =NODE.prev()
				 while(prev.length){
				 	 count++;
				 	 prev = prev.prev();
				 }
				 return count;
			}
			//return count next node
			function jsTreeGetNextPosition(NODE){
				 var count = 0;
				 var prev =NODE.next()
				 while(prev.length){
				 	 count++;
				 	 prev = prev.next();
				 }
				 return count;
			}
			jQuery(function () {
			    //bind to the form's submit event 
			    jsTree{$id}Form = jQuery('#jsTree{$id}Form').submit(function() {
			        jQuery(this).ajaxSubmit({ 
			        	dataType:'json',
				        beforeSubmit:  function(formData, jqForm, options){
				        },
				        success:       function(responseText, statusText){
				        		if(typeof(responseText.error)!='undefined' && responseText.error==false){
					        		//set value_id for node
					        		if(typeof(responseText.update_id)!='undefined'){
					        			if(jsTree{$id}Event.markLastNodeUpdate!=null){
					        				jsTree{$id}Event.markLastNodeUpdate.attr('value_id',responseText.update_id)
										}
					        		}
					        		//next action is order by move up or down
					        		if(typeof(responseText.nextRequest)!='undefined' && responseText.nextRequest!=''){
					        			jsTree{$id}Form.attr('action',responseText.nextRequest);
					        			jsTree{$id}Form.submit();
					        			jsTree{$id}Event.nextRequest = null;
									}
									//reload branch
									if(typeof(responseText.update_parent)!='undefined'){
					        			
					        			if(jsTree{$id}Event.markLastNodeUpdate!=null){
					        				jsTree{$id}Event.markLastNodeUpdate.attr('parent_id',responseText.update_parent)
					        				jsTree{$id}Event.markLastNodeUpdate.attr('id','{$id}'+'_'+responseText.update_id)
										}
										var nodeRefrech = jQuery('#{$id}'+'_'+responseText.update_id);
										jsTree{$id}Panel.jsTree.refresh(nodeRefrech);
					        		}
								}else{
									//error 
									if(typeof(responseText.msg)!='undefined'){
										alert(responseText.msg);
										if(jsTree{$id}Event.markLastNodeUpdate!=null){
											jsTree{$id}Event.markLastNodeUpdate.remove();
										}
									}
								}
								jsTree{$id}Event.markLastNodeUpdate=null;
				        },
				        clearForm: true
				    });
			        return false; 
			    });
			    
			    //params
				jsTree{$id}FormId 		= jsTree{$id}Form.find('#jsTree{$id}FormId');
				jsTree{$id}FormName 		= jsTree{$id}Form.find('#jsTree{$id}FormName');
				jsTree{$id}FormParentId 	= jsTree{$id}Form.find('#jsTree{$id}FormParentId');
				
				//setup tree 
				var {$id}conf = {
				  // Rest omitted
			      rules : {
					droppable : ['tree-drop'],
			        //multiple: 'ctrl',
			        //multitree : true,
			        //deletable : 'all',
			        draggable : 'all'

			      },
				  ui:{
				        theme_path  : '{$this->webroot}css/jstree/themes/',
				        theme_name  : '{$options['theme_name']}',
				        	
						context : [";
		if($options['context_add'])
		$html.="
						            {
						                id      : 'create',
						                label   : 'Thêm mới', 
						                icon    : 'create.png',
						                visible : function (NODE, TREE_OBJ) {TREE_OBJ.selected=NODE;if(NODE.length != 1) return false; return TREE_OBJ.check('creatable', NODE);}, 
						                action  : function (NODE, TREE_OBJ) {TREE_OBJ.create(false, TREE_OBJ.selected);} 
						            },";
		if($options['context_edit'])
		$html.="
						            { 
						                id      : 'rename',
						                label   : 'Hiệu chỉnh', 
						                icon    : 'rename.png',
						                visible : function (NODE, TREE_OBJ) { if(NODE.length != 1) return false; return TREE_OBJ.check('renameable', NODE); }, 
						                action  : function (NODE, TREE_OBJ) { TREE_OBJ.rename(); } 
						            },";
		if($options['context_copy'])
		$html.="		            {
						                id      : 'copy',
						                label   : 'Sao chép', 
						                icon    : 'copy.png',
						                visible : function (NODE, TREE_OBJ) {},
						                action  : function (NODE, TREE_OBJ) {if(jsTree{$id}Panel.jsTree.selected) { jsTree{$id}Panel.jsTree.copy(); } } 
						            },";
		if($options['context_paste'])
		$html.="		            {
						                id      : 'paste',
						                label   : 'Dán', 
						                icon    : 'paste.png',
						                visible : function (NODE, TREE_OBJ) {},
						                action  : function (NODE, TREE_OBJ) {jsTree{$id}Panel.jsTree.paste();} 
						            },";
		if($options['context_delete'])
		$html.="		            { 
						                id      : 'delete',
						                label   : 'Xóa',
						                icon    : 'remove.png',
						                visible : function (NODE, TREE_OBJ) { var ok = true; jQuery.each(NODE, function () { if(TREE_OBJ.check('deletable', this) == false) ok = false; return false; }); return ok; }, 
						                action  : function (NODE, TREE_OBJ) { jQuery.each(NODE, function () { TREE_OBJ.remove(this); }); } 
						            },";
		if($options['context_changeicon'])
		$html.="				    {
						                id      : 'changeicon',
						                label   : 'Thay đổi biểu tượng', 
						                icon    : 'ok.png',
						                visible : function (NODE, TREE_OBJ) {},
						                action  : function (NODE, TREE_OBJ) { 
						                    // Just a demo of the arguments
						                    alert(NODE.children('a').text() + ' from ' + TREE_OBJ.container.attr('id'));
						                } 
						            }";
		$html.="	    ]

				    },
			      data  : {
			      	async : true,
			      	url : '{$this->currentControllerPath}/jsChildren',
			      	type  : '{$options['type']}',
			        json  : {$data}
			      },
			      callback: {
			      	  beforechange: function(NODE,TREE_OBJ) { return true },
			      	  onchange : function (NODE,TREE_OBJ) {
			      	  	";
		if($options['theme_name']=='checkbox')
		$html.="		if(TREE_OBJ.settings.ui.theme_name == 'checkbox') {
							var _this = jQuery(NODE).is('li') ? jQuery(NODE) : jQuery(NODE).parent();
							if(_this.children('a.unchecked').size() == 0) {
								TREE_OBJ.container.find('a').addClass('unchecked');
							}
							_this.children('a').removeClass('clicked');
							if(_this.children('a').hasClass('checked')){
								var subNode = _this.find('a:first').removeClass('checked').removeClass('undetermined').addClass('unchecked');
								try{jsTree{$id}Panel.onUnChecked(NODE);}catch(e){}
								var state = 0;
							}
							else {
								var subNode = _this.find('a:first').removeClass('unchecked').removeClass('undetermined').addClass('checked');
								try{jsTree{$id}Panel.onChecked(NODE);}catch(e){}
								var state = 1;
							}
						}";
						
		$html.="	  
							try{jsTree{$id}Panel.onClick(NODE);}catch(e){};
						return true;
					  },
			      	  beforecreate: function(NODE,REF_NODE,TYPE,TREE_OBJ){
			      	  	  jsTree{$id}Event.add=true; 
			      	  	  return true; 
			      	  },
			      	  beforerename: function(NODE,LANG,TREE_OBJ) { 
			      	  	  if(jsTree{$id}Event.add==false)
			      	  	  	jsTree{$id}Event.edit=true;
			      	  	  return true 
			      	  },
			      	  onrename: function(NODE,LANG,TREE_OBJ,RB){
			      	  	//add new node
			      	  	if(jsTree{$id}Event.add){
							var url ='{$this->currentControllerPath}/add_ajax';
				      	  	
							//get data
							var tmpNode     =jQuery(NODE);
							var tmpParentId =tmpNode.parent().parent().attr('value_id');
				      	  	jsTree{$id}FormId.attr('value',tmpNode.attr('value_id'));
				      	  	jsTree{$id}FormName.attr('value',tmpNode.find('a:first').html());
				      	  	
				      	  	jsTree{$id}FormParentId.attr('value',tmpParentId);
				      	  	
				      	  	//update current node
				      	  	tmpNode.attr('parent_id',tmpParentId);
				      	  	
				      	  	jsTree{$id}Form.attr('action',url);
				      	  	jsTree{$id}Form.submit();
				      	  	
				      	  	jsTree{$id}Event.markLastNodeUpdate = tmpNode;
				      	  	
				      	  	//reset event
				      	  	jsTree{$id}Event.add=false;
						}
						//edit or rename
						if(jsTree{$id}Event.edit){
							var url ='{$this->currentControllerPath}/edit_ajax';
				      	  	
				      	  	//get data
				      	  	var tmpNode     =jQuery(NODE);
				      	  	jsTree{$id}FormId.attr('value',tmpNode.attr('value_id'));
				      	  	jsTree{$id}FormName.attr('value',tmpNode.find('a:first').html());
				      	  	
				      	  	jsTree{$id}FormParentId.attr('value',tmpNode.parent().parent().attr('value_id'));
				      	  	
				      	  	jsTree{$id}Form.attr('action',url)
				      	  	jsTree{$id}Form.submit();
				      	  	
				      	  	//reset event
				      	  	jsTree{$id}Event.edit=false;
						}
			      	  },
			      	  beforedelete: function(NODE,TREE_OBJ) { return confirm('Are you sure you want to delete?');}, 
			      	  ondelete    : function(NODE, TREE_OBJ,RB) { 
							var url ='{$this->currentControllerPath}/delete_ajax';
				      	  	//jQuery.post(url,function(){});
				      	  	
				      	  	//get data
				      	  	var tmpNode     =jQuery(NODE);
				      	  	jsTree{$id}FormId.attr('value',tmpNode.attr('value_id'));
				      	  	jsTree{$id}FormName.attr('value',tmpNode.find('a:first').html());
				      	  	
							jsTree{$id}Form.attr('action',url)
				      	  	jsTree{$id}Form.submit();
			      	  },
			      	  beforemove  : function(NODE,REF_NODE,TYPE,TREE_OBJ) {
				      	  //get data
				      	  	var tmpNode     =jQuery(NODE);
				      	  //old position
				      	  	  jsTree{$id}Event.countPrev = jsTreeGetPosition(tmpNode);
			      	  	   return true;
					  }, 
			      	  onmove      : function(NODE,REF_NODE,TYPE,TREE_OBJ,RB) { 
			      	  	  	var url ='{$this->currentControllerPath}/move_parent_ajax';
			      	  	    
							//get data
							var tmpNode     =jQuery(NODE);
			      	  	    
			      	  	    //if(tmpNode.parent().parent().attr('id')=='{$id}'){
			      	  	    // 	jsTree{$id}FormParentId.attr('value','');
							//}else{
			      	  	    //	jsTree{$id}FormParentId.attr('value',tmpNode.parent().parent().attr('value_id'));
							//}
			      	  	    jsTree{$id}FormParentId.attr('value',tmpNode.parent().parent().attr('value_id'));
			      	  	    jsTree{$id}FormId.attr('value',tmpNode.attr('value_id'));
			      	  	    
			      	  	    //move to edit parent_id
		      	  	    	if(jsTree{$id}FormParentId.attr('value')!= tmpNode.attr('parent_id')){

								//set current parent_id for DOM
								tmpNode.attr('parent_id',jsTree{$id}FormParentId.attr('value'));
								
								//action move up after change parent_id
								var move = jsTreeGetNextPosition(tmpNode);
								jsTree{$id}Event.nextRequest =tmpNode.attr('value_id')+','+move;
								jsTree{$id}FormName.attr('value',jsTree{$id}Event.nextRequest);
								jsTree{$id}Form.attr('action',url)
				      	  		jsTree{$id}Form.submit();
							}else{
								//order up or down
								var newPosition = jsTreeGetPosition(tmpNode);
								var move = newPosition-jsTree{$id}Event.countPrev;
								//move down
								if(move>0){
									url='{$this->currentControllerPath}/movedown_ajax/'+tmpNode.attr('value_id')+'/'+move;
									
									jsTree{$id}Form.attr('action',url)
					      	  		jsTree{$id}Form.submit();
					      	  	//move up
								}else if(move<0){
									url='{$this->currentControllerPath}/moveup_ajax/'+tmpNode.attr('value_id')+'/'+move;
									
									jsTree{$id}Form.attr('action',url)
					      	  		jsTree{$id}Form.submit();
								}
								
							}
			      	  	jsTree{$id}Event.countPrev = null;
			      	  },
			      	  onrgtclk    : function(NODE, TREE_OBJ, EV) {
			      	  	  //TREE_OBJ.select_branch.call(TREE_OBJ, NODE);
			      	  },
			      	  oncopy      : function(NODE,REF_NODE,TYPE,TREE_OBJ,RB) {
			      	  	
						//get data
						var tmpNode     = jQuery(NODE);
						var ref_node	= jQuery(REF_NODE);

						var url='{$this->currentControllerPath}/copy_ajax/'+tmpNode.attr('value_id');						
						url+='/'+ref_node.attr('value_id');
						
						jsTree{$id}Event.markLastNodeUpdate = tmpNode;
						
						jsTree{$id}Form.attr('action',url)
		      	  		jsTree{$id}Form.submit();
			      	  }
        	      }
			    };
			    jsTree{$id}Panel.jsTree = jQuery.tree_create();
				jsTree{$id}Panel.jsTree.init(jQuery('#{$id}'),jQuery.extend({},{$id}conf));
			    
			    jsTree{$id}Panel.create	= function () { jsTree{$id}Panel.jsTree.create(false, (jsTree{$id}Panel.jsTree.container.find('li').size() == 0 ? -1 : false) ); }
				jsTree{$id}Panel.rename	= function () { jsTree{$id}Panel.jsTree.rename(); }
				jsTree{$id}Panel.remove	= function () { jsTree{$id}Panel.jsTree.remove(); }
				jsTree{$id}Panel.copy	= function () { if(jsTree{$id}Panel.jsTree.selected) { jsTree{$id}Panel.jsTree.copy(); } }
				jsTree{$id}Panel.cut	= function () { if(jsTree{$id}Panel.jsTree.selected) { jsTree{$id}Panel.jsTree.cut(); } }
				jsTree{$id}Panel.paste	= function () { jsTree{$id}Panel.jsTree.paste(); }
			    
			    
				// Interface hooks
				jQuery('#{$id}tree-panel .menu')
					.find('a').not('.lang')
						.bind('click', function () {
							try {jsTree{$id}Panel[jQuery(this).attr('rel')](); } catch(err) { }
							this.blur();
						})
						.end().end()
					.children('.cmenu')
						.hover( function () { jQuery(this).addClass('hover'); }, function () { jQuery(this).removeClass('hover') })
						    
			});

		";
		return $this->Javascript->codeBlock($html).$form;
	}
	/**
	* _ListJson is parser data tree
 	* @return formant of jstree.com
 	* @return string content code block javascript include tag <script ...>
 	* @access private
	**/
	function _ListJson($data) {
		$output = "[";
		//Debug($data);exit;
		if(!is_array($data)) return '""';
		foreach ($data as $key => $row) {
			$_name = $row[$this->model]['name'];
			$_id_name = $this->idDOM;//$this->_format_unsigned($row[$this->model]['name']);
			$_id = $row[$this->model]['id'];
			$_parent_id = $row[$this->model]['parent_id'];
			
			$output .= "{attributes:{id:'{$_id_name}_{$_id}',value_id:'{$_id}',parent_id:'{$_parent_id}'}, ";
			if($row[$this->model]['rght']-$row[$this->model]['lft']>1)
				$output.= "state: 'closed', ";
			
			$output.= "data:'{$_name}' ";
			if(isset($row['children'][0])){
				$output .= ',children:'.$this->_ListJson($row['children']);
				$output .= '}';
			}else{
				$output .= "},";
			}
		}
		return $output."]";
	}
}
?>